﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Model
{
    public class EditorAction
    {
        protected DocumentRuntime docRt;
        protected IDocumentEditor docEditor;
        protected CommandCenter commandCenter;
        protected ICommandControl commandCtrl;
        protected Model3DEditRuntime model3dRuntime;
        protected Snap3dRuntime snap3dRuntime;
        public EditorAction(IDocumentEditor docEditor)
        {
            this.docEditor = docEditor;
            this.docRt = docEditor.DocRt;
            this.commandCenter = this.docEditor.CommandCenter;
            this.commandCtrl = this.commandCenter.Commander;
            this.model3dRuntime = docEditor as Model3DEditRuntime;
            this.snap3dRuntime = this.model3dRuntime.Snap3DRuntime;
        }
        public async void PushPull(string[] args)
        {
            StartAction();
            FaceInputerResult pr = null;
            PlanarSurface3d plane = null;
            LcSolid3d solidEle = null;
            CancellationTokenSource finishToken = null;
            double pullDist = 0;
            void onMouseEvent(string name, MouseEventRuntime mer)
            {
                if (name == "Move")
                {
                    if (solidEle != null && pr != null)
                    {
                        Move(this.snap3dRuntime.SnapPoint);
                    }
                }
                else if (name == "Up")
                {

                }
            }
            void Move(Vector3 target)
            {
                var pullTotal = (target - pr.SnapPoint).Dot(plane.Normal);
                var offset = pullTotal - pullDist;
                pullDist = pullTotal;
                solidEle.PushOrPullFace(plane, offset);
            }

        step0:
            var planeInputer = new SurfaceInputer3d(this.docEditor);
            var result = await planeInputer.Execute("选中一个面");
            if (result?.IsCancelled ?? true)
                goto cancel;
            pr = result.ValueX as FaceInputerResult;
            if (pr.Surface is PlanarSurface3d)
                goto step1;
            else
                goto step0;
            step1:
            plane = pr.Surface as PlanarSurface3d;
            solidEle = pr.Element as LcSolid3d;
            this.model3dRuntime.EnableCameraControl(false);
            var camera = this.snap3dRuntime.GetCamera();
            var yAxis = camera.getWorldDirection().Negate().Cross(plane.Normal).Normalize();
            var zAxis = plane.Normal.Clone().Cross(yAxis).Normalize();
            this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
            {
                new Plane().SetFromNormalAndCoplanarPoint(zAxis,pr.SnapPoint)
            });
            this.model3dRuntime.Control.AttachEvents(null, null, onMouseEvent, null, null, null, null);
            var pointer = new PointInputer3d(docEditor);
            var presult = await pointer.Execute("推拉平面", SnapFilterType.OnlyPlane);
            this.model3dRuntime.Control.DetachEvents(null, null, onMouseEvent, null, null, null, null);
            this.snap3dRuntime.ClearSnapPlanes();
            this.model3dRuntime.EnableCameraControl(true);
            if (presult.IsCancelled)
                goto cancel;
            var target = (presult.ValueX as Vector3);

        cancel:
        end:
            EndAction();

        }
        private void StartAction()
        {
            this.docEditor.CommandCenter.InAction = true;
        }
        private void EndAction()
        {
            this.commandCtrl.Prompt(string.Empty);

            this.commandCtrl.SetCurMethod(null);
            this.commandCtrl.SetCurStep(null);
            this.docEditor.CommandCenter.InAction = false;
        }
    }
}
